﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Xml;
using System.Text;
using _7DaysToDieTools;
using Mono.Cecil;
using Mono.Cecil.Cil;

namespace _7DaysToDieTools.Class
{
    /// <summary>
    /// 背包处理相关类
    /// </summary>
    public static class BagAction
    {
        /// <summary>
        /// 设置大背包DLL
        /// </summary>
        /// <param name="dllPath">DLL路径</param>
        /// <param name="BagSize">背包格数</param>
        public static void BagSet(string dllPath,int BagSize)
        {
            DefaultAssemblyResolver dar = new DefaultAssemblyResolver();
            dar.AddSearchDirectory(new DirectoryInfo(dllPath).Parent.FullName);
            ModuleDefinition md = null;
            
            try
            {
                md = ModuleDefinition.ReadModule(dllPath, new ReaderParameters { AssemblyResolver = dar });
            }
            catch
            {
                throw new Exception("无法调用要修改的DLL");
            }
            //Bag-SC-默认参数
            md.Types.FirstOrDefault(o => o.Name == "Bag").Methods.FirstOrDefault(m => m.HasParameters && m.Parameters.Count == 1 && m.Parameters[0].HasConstant).Parameters[0].Constant = BagSize;
            //ass.MainModule.Types.FirstOrDefault(o => o.Name == "Bag").Methods.FirstOrDefault(m => m.Parameters[0].GetType() == typeof(SByte)).Parameters[0].Constant = BagSize;
            //Bag-GetSlots-内部函数参数
            md.Types.FirstOrDefault(o => o.Name == "Bag").Methods.FirstOrDefault(m => m.Name == "GetSlots").Body.Instructions.FirstOrDefault(I => I.OpCode == OpCodes.Ldc_I4_S).Operand = Convert.ToSByte(BagSize);
            //Bag-SetSlots-内部函数参数
            md.Types.FirstOrDefault(o => o.Name == "Bag").Methods.FirstOrDefault(m => m.Name == "SetSlots").Body.Instructions.FirstOrDefault(I => I.OpCode == OpCodes.Ldc_I4_S).Operand = Convert.ToSByte(BagSize);
            //Bag-AddItem-内部函数参数
            md.Types.FirstOrDefault(o => o.Name == "Bag").Methods.FirstOrDefault(m => m.Name == "AddItem").Body.Instructions.FirstOrDefault(I => I.OpCode == OpCodes.Ldc_I4_S).Operand = Convert.ToSByte(BagSize);

            //PlayerDataFile-Read-内部参数(3个)
            MethodDefinition mdTmp = null;
            if (Sinfo.gameType == Sinfo.GameType.Client)
            {
                mdTmp = md.Types.FirstOrDefault(o => o.Name == "PlayerDataFile").Methods.FirstOrDefault(m => m.Name == "Read");
                mdTmp.Body.Instructions.FirstOrDefault(I => I.Offset == 136).Operand = Convert.ToSByte(BagSize);
                mdTmp.Body.Instructions.FirstOrDefault(I => I.Offset == 159).Operand = Convert.ToSByte(BagSize);
                mdTmp.Body.Instructions.FirstOrDefault(I => I.Offset == 176).Operand = Convert.ToSByte(BagSize);
            }
            else if (Sinfo.gameType == Sinfo.GameType.Server)
            {
                mdTmp = md.Types.FirstOrDefault(o => o.Name == "PlayerDataFile").Methods.FirstOrDefault(m => m.Name == "Read");
                mdTmp.Body.Instructions.FirstOrDefault(I => I.Offset == 140).Operand = Convert.ToSByte(BagSize);
                mdTmp.Body.Instructions.FirstOrDefault(I => I.Offset == 144).Operand = Convert.ToSByte(BagSize);
                mdTmp.Body.Instructions.FirstOrDefault(I => I.Offset == 161).Operand = Convert.ToSByte(BagSize);
            }

            //保存
            md.Write(dllPath);
        }

        /// <summary>
        /// 设置112格背包
        /// </summary>
        public static void SetBigBackpack112()
        {
            try
            {
                //定义背包宽度变量
                int BWidth = 1206;
                string tmpPath = "";
                //修改xui.xml ，设置缩放比例
                XmlDocument xDoc = new XmlDocument();
                XmlElement xe = null;
                tmpPath = Sinfo.Path.Config + Sinfo.File.Xui;
                xDoc.Load(tmpPath);
                xe = xDoc.ChildNodes[0].ChildNodes[0] as XmlElement;
                xe.SetAttribute("scale", "0.92");
                xe.SetAttribute("stackpanel_scale", "1.05");
                xDoc.Save(tmpPath);

                //修改windows.xml ，设置背包界面
                xDoc = new XmlDocument();
                tmpPath = Sinfo.Path.XUi + Sinfo.File.XuiWindows;
                xDoc.Load(tmpPath);

                //空的物品信息框
                xe = xDoc.SelectSingleNode("/windows/window[@name='emptyInfoPanel']") as XmlElement;
                xe.SetAttribute("width", BWidth.ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='emptyInfoPanel']/rect/sprite[@name='backgroundMain']") as XmlElement;
                xe.SetAttribute("width", "100%");

                //物品信息框
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']") as XmlElement;
                xe.SetAttribute("width", BWidth.ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']/panel/label[@text='{pricelabel} {itemcost}{markup}']") as XmlElement;
                xe.SetAttribute("pos", (BWidth - 253).ToString() + ",-8");
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']/panel/sprite[@name='costIcon']") as XmlElement;
                xe.SetAttribute("pos", (BWidth - 26).ToString() + ",-10");
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']/rect[@name='contentInfo']/sprite[@name='backgroundMain']") as XmlElement;
                xe.SetAttribute("width", "100%");
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']/rect[@name='contentInfo']/rect[@name='description' and @depth='1']") as XmlElement;
                xe.SetAttribute("width", (BWidth - 156).ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']/rect[@name='contentInfo']/rect[@name='description' and @depth='1']/sprite[@name='backgroundMain']") as XmlElement;
                xe.SetAttribute("width", (BWidth - 150).ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']/rect[@name='contentInfo']/rect[@name='description' and @depth='2']") as XmlElement;
                xe.SetAttribute("width", (BWidth - 156).ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']/rect[@name='contentInfo']/rect[@name='description' and @depth='2']/sprite[@name='backgroundMain']") as XmlElement;
                xe.SetAttribute("width", (BWidth - 150).ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']/rect[@name='contentInfo']/grid[@name='parts']") as XmlElement;
                xe.SetAttribute("cols", "14");

                //背包定义
                xe = xDoc.SelectSingleNode("/windows/window[@name='windowBackpack']") as XmlElement;
                xe.SetAttribute("width", BWidth.ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='windowBackpack']/panel[@name='header']/label[@text='{currencyamount}']") as XmlElement;
                xe.SetAttribute("pos", (BWidth - 131).ToString() + ",-8");
                xe = xDoc.SelectSingleNode("/windows/window[@name='windowBackpack']/panel[@name='header']/sprite[@name='costIcon']") as XmlElement;
                xe.SetAttribute("pos", (BWidth - 26).ToString() + ",-10");
                xe = xDoc.SelectSingleNode("/windows/window[@name='windowBackpack']/panel[@name='content']/sprite[@name='backgroundMain']") as XmlElement;
                xe.SetAttribute("width", "100%");
                xe = xDoc.SelectSingleNode("/windows/window[@name='windowBackpack']/panel[@name='content']/grid[@name='inventory']") as XmlElement;
                xe.SetAttribute("rows", "7");
                xe.SetAttribute("cols", "16");

                //Buff信息窗口
                xe = xDoc.SelectSingleNode("/windows/window[@name='buffInfoPanel']") as XmlElement;
                xe.SetAttribute("width", BWidth.ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='buffInfoPanel']/rect[@name='contentBuffInfo']/rect/sprite[@name='backgroundMain' and @depth='5']") as XmlElement;
                xe.SetAttribute("width", BWidth.ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='buffInfoPanel']/rect[@name='contentBuffInfo']/rect/rect[@name='description' and @depth='1']") as XmlElement;
                xe.SetAttribute("width", (BWidth - 156).ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='buffInfoPanel']/rect[@name='contentBuffInfo']/rect/rect[@name='description' and @depth='1']/sprite[@name='backgroundMain']") as XmlElement;
                xe.SetAttribute("width", "100%");
                xe = xDoc.SelectSingleNode("/windows/window[@name='buffInfoPanel']/rect[@name='contentBuffInfo']/rect/rect[@name='description' and @depth='1']/label[@name='statText']") as XmlElement;
                xe.SetAttribute("width", "100%");
                xe = xDoc.SelectSingleNode("/windows/window[@name='buffInfoPanel']/rect[@name='contentBuffInfo']/rect/rect[@name='description' and @depth='2']") as XmlElement;
                xe.SetAttribute("width", (BWidth - 156).ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='buffInfoPanel']/rect[@name='contentBuffInfo']/rect/rect[@name='description' and @depth='2']/label[@name='descriptionText']") as XmlElement;
                xe.SetAttribute("width", "100%");
                xe = xDoc.SelectSingleNode("/windows/window[@name='buffInfoPanel']/rect[@name='contentBuffInfo']/rect/grid[@controller='BuffItemList']") as XmlElement;
                xe.SetAttribute("cols", "14");

                xDoc.Save(tmpPath);
            }
            catch(Exception x)
            {
                throw new Exception("修改112格背包xml文件出错：" + x.Message, x);
            }
            try
            {
                BagSet(Sinfo.Path.Dll + Sinfo.File.GameDllAssembly, 112);
            }
            catch(Exception x)
            {
                throw new Exception("修改112格背包DLL文件出错：" + x.Message, x);
            }
        }

        /// <summary>
        /// 设置56格背包
        /// </summary>
        public static void SetBigBackpack56()
        {
            try
            {
                //定义背包宽度变量
                int BWidth = 603;
                string tmpPath = "";
                //修改xui.xml ，设置缩放比例
                XmlDocument xDoc = new XmlDocument();
                XmlElement xe = null;
                tmpPath = Sinfo.Path.Config + Sinfo.File.Xui;
                xDoc.Load(tmpPath);
                xe = xDoc.ChildNodes[0].ChildNodes[0] as XmlElement;
                xe.SetAttribute("scale", "0.92");
                xe.SetAttribute("stackpanel_scale", "1.05");
                xDoc.Save(tmpPath);

                //修改windows.xml ，设置背包界面
                xDoc = new XmlDocument();
                tmpPath = Sinfo.Path.XUi + Sinfo.File.XuiWindows;
                xDoc.Load(tmpPath);

                //空的物品信息框
                xe = xDoc.SelectSingleNode("/windows/window[@name='emptyInfoPanel']") as XmlElement;
                xe.SetAttribute("width", BWidth.ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='emptyInfoPanel']/rect/sprite[@name='backgroundMain']") as XmlElement;
                xe.SetAttribute("width", "100%");

                //物品信息框
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']") as XmlElement;
                xe.SetAttribute("width", BWidth.ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']/panel/label[@text='{pricelabel} {itemcost}{markup}']") as XmlElement;
                xe.SetAttribute("pos", (BWidth - 253).ToString() + ",-8");
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']/panel/sprite[@name='costIcon']") as XmlElement;
                xe.SetAttribute("pos", (BWidth - 26).ToString() + ",-10");
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']/rect[@name='contentInfo']/sprite[@name='backgroundMain']") as XmlElement;
                xe.SetAttribute("width", "100%");
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']/rect[@name='contentInfo']/rect[@name='description' and @depth='1']") as XmlElement;
                xe.SetAttribute("width", (BWidth - 156).ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']/rect[@name='contentInfo']/rect[@name='description' and @depth='1']/sprite[@name='backgroundMain']") as XmlElement;
                xe.SetAttribute("width", (BWidth - 150).ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']/rect[@name='contentInfo']/rect[@name='description' and @depth='2']") as XmlElement;
                xe.SetAttribute("width", (BWidth - 156).ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']/rect[@name='contentInfo']/rect[@name='description' and @depth='2']/sprite[@name='backgroundMain']") as XmlElement;
                xe.SetAttribute("width", (BWidth - 150).ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='itemInfoPanel']/rect[@name='contentInfo']/grid[@name='parts']") as XmlElement;
                xe.SetAttribute("cols", "6");

                //背包定义
                xe = xDoc.SelectSingleNode("/windows/window[@name='windowBackpack']") as XmlElement;
                xe.SetAttribute("width", BWidth.ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='windowBackpack']/panel[@name='header']/label[@text='{currencyamount}']") as XmlElement;
                xe.SetAttribute("pos", (BWidth - 131).ToString() + ",-8");
                xe = xDoc.SelectSingleNode("/windows/window[@name='windowBackpack']/panel[@name='header']/sprite[@name='costIcon']") as XmlElement;
                xe.SetAttribute("pos", (BWidth - 26).ToString() + ",-10");
                xe = xDoc.SelectSingleNode("/windows/window[@name='windowBackpack']/panel[@name='content']/sprite[@name='backgroundMain']") as XmlElement;
                xe.SetAttribute("width", "100%");
                xe = xDoc.SelectSingleNode("/windows/window[@name='windowBackpack']/panel[@name='content']/grid[@name='inventory']") as XmlElement;
                xe.SetAttribute("rows", "7");
                xe.SetAttribute("cols", "8");

                //Buff信息窗口
                xe = xDoc.SelectSingleNode("/windows/window[@name='buffInfoPanel']") as XmlElement;
                xe.SetAttribute("width", BWidth.ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='buffInfoPanel']/rect[@name='contentBuffInfo']/rect/sprite[@name='backgroundMain' and @depth='5']") as XmlElement;
                xe.SetAttribute("width", BWidth.ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='buffInfoPanel']/rect[@name='contentBuffInfo']/rect/rect[@name='description' and @depth='1']") as XmlElement;
                xe.SetAttribute("width", (BWidth - 156).ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='buffInfoPanel']/rect[@name='contentBuffInfo']/rect/rect[@name='description' and @depth='1']/sprite[@name='backgroundMain']") as XmlElement;
                xe.SetAttribute("width", "100%");
                xe = xDoc.SelectSingleNode("/windows/window[@name='buffInfoPanel']/rect[@name='contentBuffInfo']/rect/rect[@name='description' and @depth='1']/label[@name='statText']") as XmlElement;
                xe.SetAttribute("width", "100%");
                xe = xDoc.SelectSingleNode("/windows/window[@name='buffInfoPanel']/rect[@name='contentBuffInfo']/rect/rect[@name='description' and @depth='2']") as XmlElement;
                xe.SetAttribute("width", (BWidth - 156).ToString());
                xe = xDoc.SelectSingleNode("/windows/window[@name='buffInfoPanel']/rect[@name='contentBuffInfo']/rect/rect[@name='description' and @depth='2']/label[@name='descriptionText']") as XmlElement;
                xe.SetAttribute("width", "100%");
                xe = xDoc.SelectSingleNode("/windows/window[@name='buffInfoPanel']/rect[@name='contentBuffInfo']/rect/grid[@controller='BuffItemList']") as XmlElement;
                xe.SetAttribute("cols", "6");

                xDoc.Save(tmpPath);
            }
            catch(Exception x)
            {
                throw new Exception("修改56格背包xml文件出错：" + x.Message, x);
            }
            try
            {
                BagSet(Sinfo.Path.Dll + Sinfo.File.GameDllAssembly, 56);
            }
            catch(Exception x)
            {
                throw new Exception("修改56格背包DLL文件出错：" + x.Message, x);
            }
        }
    }
}
